Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

Проблема... деревья в MySQL (Fally)
Author Message
Fally
Заглянувший



Joined: 02 Dec 2006
Posts: 10
Карма: -1
   поощрить/наказать


PostPosted: Sat Dec 02, 2006 10:49 am (написано за 7 минут 27 секунд)
   Post subject: Проблема... деревья в MySQL
Reply with quote

Здравствуйте.
Я занимаюсь разработкой онлайн игры. И захотелось пооригинальничать. Я решил сделать древовидную систему скиллов, и так, что чтобы прокачать один скилл необходимо сначала прокачать n-нное число других скиллов, при этом каждый из родительских скиллов прокачивается разное кол-во раз. В БД я использовал две таблицы:
1) Skills
SkillID|SkillName|...|SkillHaveParents(BOOLEAN)|SkillCountParents
2) Parents4Childs:
ChildID|NeedParentLvl|ParentID

По моей задумке результирующий массив будет выглядеть таким образом:
Code (php): скопировать код в буфер обмена
$_Tree = array (www.php.net/array)(
        '[name] 1' => array (www.php.net/array)(
                                        '{Skill}ID' => "",
                                        '{Skill}Name' => "",
                                        '{Skill}CanUse' => "",
                                        '{Skill}Type' => "",
                                        '{Skill}Lvl' => "",
                                        '{Skill}Desc' => "",
                                        '{Skill}MaxLvl' => "",
                                        '{Skill}Damage' => "",
                                        '{Skill}Upping' => "",
                                        '{Skill}Effect' => "",
                                        '{Skill}HaveParents' => "",
                                        '{Skill}CountParents' => "",
                                        '{Skill}Parents' => array (www.php.net/array)(
                                                                '{Skill}Name_1(parent)' => array (www.php.net/array)(
                                                                                                        'parent{Skill}ID' => "",
                                                                                                        'parent{Skill}Name' => "",
                                                                                                        'parent{Skill}Lvl' => "",
                                                                                                        'parent{Skill}NeedLvl' => "",
                                                                                                        'parent{Skill}CanUse' => "",
                                                                                                                              ),
                                                                '{Skill}Name_2(parent)' => array (www.php.net/array)(
                                                                                                        'parent{Skill}ID' => "",
                                                                                                        'parent{Skill}Name' => "",
                                                                                                        'parent{Skill}Lvl' => "",
                                                                                                        'parent{Skill}NeedLvl' => "",
                                                                                                        'parent{Skill}CanUse' => "",
                                                                                                            ),
                                                                //
                                                                                           )
                                                            ),
                                                            //
 
Вся проблема возникла в создании SQL-запроса к этим таблицам, вопрос как его лучше оформить? и параллельный вопрос можно ли сделать так, чтобы при формировании запроса и обработке его результата функцией mysql_fetch_assoc РНР возвращал двумерный трехмерный массивы...
Заранее Благодарен.
С Ув. Кирилл.
Back to top
View user's profile Send private message
Kupuyc
Участник форума



Joined: 31 Mar 2006
Posts: 146
Карма: 5
   поощрить/наказать


PostPosted: Sun Dec 03, 2006 10:00 am (спустя 23 часа 11 минут; написано за 2 минуты 9 секунд)
   Post subject:
Reply with quote

mysql_fetch_assoc всегда возвращает ассоциативный массив представляющий из себя некоторую строку результата запроса. Т.о. говорить о составлении запроса одним махом решающего Вашу проблему пока рановато. Да и таблички у вас под это дело несколько странноватые, имхо. Может сначала погуглить?
Back to top
View user's profile Send private message
Fally
Заглянувший



Joined: 02 Dec 2006
Posts: 10
Карма: -1
   поощрить/наказать


PostPosted: Sun Dec 03, 2006 4:59 pm (спустя 6 часов 58 минут; написано за 37 секунд)
   Post subject:
Reply with quote

А как реализовать правильно таблицы? И чем они странноваты... аргументируйте пожалуйста своё сообщение.
Back to top
View user's profile Send private message
Kupuyc
Участник форума



Joined: 31 Mar 2006
Posts: 146
Карма: 5
   поощрить/наказать


PostPosted: Mon Dec 04, 2006 6:00 pm (спустя 1 день 1 час 49 секунд; написано за 2 минуты 51 секунду)
   Post subject:
Reply with quote

Странноваты тем, что (имхо, опять же) под эту задачу очень хорошо подходят nested sets. Стало быть, в моем понимании приведенные таблички - "Велосипед 2.0". Довольно неплохо об этой реализации деревьев изложено тут (phpclub.ru/detail/article/db_tree), да и на этом форуме она более чем один раз была обсуждаема.
Back to top
View user's profile Send private message
Fally
Заглянувший



Joined: 02 Dec 2006
Posts: 10
Карма: -1
   поощрить/наказать


PostPosted: Mon Dec 04, 2006 11:40 pm (спустя 5 часов 39 минут; написано за 2 минуты 59 секунд)
   Post subject:
Reply with quote

Согласен с вами, в том что в приведённой вами статье хорошо описана реализация, но она мне не подходит.... т.к. у каждого узла в моём случае может быть n-ое количество родителей... инами словами nested sets здесь не подходит.... но я не спорю с вами, возможно с этим кто-то до меня уже сталкивался... и я изобретаю велосипед.. но я хочу сам разобраться с этой проблемой... для самообразования и самоссовершенствования..... но на деле всё оказалось не так легко... поэтому решил обратиться на форум за помощью...
Back to top
View user's profile Send private message
Никита Косолaпов
Участник форума



Joined: 08 Aug 2006
Posts: 172
Карма: 9
   поощрить/наказать

Location: Москва

PostPosted: Tue Dec 05, 2006 12:50 pm (спустя 13 часов 10 минут; написано за 2 минуты 16 секунд)
   Post subject:
Reply with quote

А дерево ли это?
Если родитель имеет не более одного потомка - то дерево, только перевернутое.
А если родитель может иметь более чем одного потомка - то это уже больше на сеть похоже (или как правильно называется такая структура?)

Fally, уточните задачу, пожалуйста?
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Tue Dec 05, 2006 1:11 pm (спустя 21 минуту; написано за 3 минуты 10 секунд)
   Post subject:
Reply with quote

По большому счёту - это некий ориентированный граф.
Соответственно, читайте про хранение графов в РСУБД.

Я (бы) делал так:
Отдельная таблица со скилами, отдельная - связи между ними.
Тогда в таблицу связей можно будет внести некие коэффициенты и при выборке производить вычисления над ними. Ну и уже по результатам этих вычислений показывать выбранное или нет.
Back to top
View user's profile Send private message
Fally
Заглянувший



Joined: 02 Dec 2006
Posts: 10
Карма: -1
   поощрить/наказать


PostPosted: Tue Dec 05, 2006 3:47 pm (спустя 2 часа 35 минут; написано за 6 минут 31 секунду)
   Post subject:
Reply with quote

Никита Косолaпов:
в проэкте я планирую сделать развитую систему скиллов, как в Ragnarok Online, т.е. есть n-ое количество скиллов. Некоторые из них можно прокачать в любое время, только при наличии очков для прокачивания, но есть и такие скиллы, которые можно прокачать только в том случае, если прокачено k-ое количество определённых скиллов, при этом каждый k-ый скилл необходимо прокачать разное количество раз.

Вот как это выглядит в текстовом виде.

1) Скилл №1; макс уровень 10; дополн. скиллов не требуется;
2) Скилл №2; макс уровень 5; дополн. скиллов не требуется;
3) Скилл №3; макс уровень 8; дополн. скиллов не требуется;
4) Скилл №4; макс уровень 10; необходимо прокачать Скилл №1 до 3 уровня, Скилл №2 до 2 уровня, Скилл №3 до 8 уровня.

WingedFox:
Спасибо за совет, но не могли бы Вы получше написать о коэффициентах? Вроде бы у меня промежуточная таблица Parents4Childs так и выглядела.
Back to top
View user's profile Send private message
Никита Косолaпов
Участник форума



Joined: 08 Aug 2006
Posts: 172
Карма: 9
   поощрить/наказать

Location: Москва

PostPosted: Tue Dec 05, 2006 4:31 pm (спустя 43 минуты; написано за 4 минуты 3 секунды)
   Post subject:
Reply with quote

Skill:
SkillID, MaxLev, SkillName, SkillHaveParents

1; 10; Скилл 1; 0;
2; 5; Скилл 2; 0;
3; 8; Скилл 3; 0;
4; 10; Скилл 4; 1;


Parents:
SkillID, ParentSkillID, Level

4; 1; 3;
4; 2; 2;
4; 3; 8;


вроде так...
Back to top
View user's profile Send private message Send e-mail
Fally
Заглянувший



Joined: 02 Dec 2006
Posts: 10
Карма: -1
   поощрить/наказать


PostPosted: Tue Dec 05, 2006 5:02 pm (спустя 31 минуту; написано за 2 минуты 28 секунд)
   Post subject:
Reply with quote

Ну у меня так БД и реализована... :)
Но как я уже написал в первом сообщении, у меня проблема в создании SQL-запроса к БД. Который мог бы извлекать из БД не только информацию о дочерних скиллах, но и информацию о родителях (их ID, и необходимый их уровень для использования данного скилла)
Back to top
View user's profile Send private message
Никита Косолaпов
Участник форума



Joined: 08 Aug 2006
Posts: 172
Карма: 9
   поощрить/наказать

Location: Москва

PostPosted: Tue Dec 05, 2006 5:07 pm (спустя 5 минут; написано за 1 минуту 31 секунду)
   Post subject:
Reply with quote

Code (SQL): скопировать код в буфер обмена
SELECT ParentSkillID, Level FROM `Parents` WHERE `SkillID` = 4
вытаскивает инфу именно о родителях.
А вот о детях...
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Tue Dec 05, 2006 5:33 pm (спустя 26 минут; написано за 33 секунды)
   Post subject:
Reply with quote

Обычный LEFT JOIN достаточен.
Back to top
View user's profile Send private message
Fally
Заглянувший



Joined: 02 Dec 2006
Posts: 10
Карма: -1
   поощрить/наказать


PostPosted: Tue Dec 05, 2006 5:37 pm (спустя 4 минуты; написано за 57 секунд)
   Post subject:
Reply with quote

это то я понимаю... но дело в том, что я пытался реализовать выборку одним запросом... но не получалось или же вложенный запрос возвращал не одно значение.
Суть такова:
Code (SQL): скопировать код в буфер обмена
SELECT SkillID, SkillName, MaxLev FROM `Skills` JOIN `Parents` ON Skills.SkillID=Parents.SkillID
... это выборка родителей всех существующих, но ещё нужно, чтобы в результирующую структуру данных так же чтоб результат был примерно такой:

SkillID; SkillName; MaxLev; ChildID;

ChildID - ID дочернего скилла.

Вся проблема состоит в правильном формировании запроса к БД.
Back to top
View user's profile Send private message
Никита Косолaпов
Участник форума



Joined: 08 Aug 2006
Posts: 172
Карма: 9
   поощрить/наказать

Location: Москва

PostPosted: Tue Dec 05, 2006 6:20 pm (спустя 42 минуты; написано за 1 минуту 3 секунды)
   Post subject:
Reply with quote

то есть результатом должно быть следующее:
1; Скилл 1; 10; 4;
2; Скилл 2; 5; 4;
3; Скилл 3; 8; 4;
4; Скилл 4; 10; 0;

Или я не правильно понял?
Back to top
View user's profile Send private message Send e-mail
Fally
Заглянувший



Joined: 02 Dec 2006
Posts: 10
Карма: -1
   поощрить/наказать


PostPosted: Tue Dec 05, 2006 6:28 pm (спустя 7 минут; написано за 2 минуты 38 секунд)
   Post subject:
Reply with quote

да... согласно моему вопросу так... но это моя вина... не правильно я сформулировал... долдно быть так:
SkillID;SkillName;MaxLev;NeedLev;ParentID
1; Скилл 4; 10; 1;
1; Скилл 4; 5; 2;
1; Скилл 4; 8; 3;
1; Скилл 4; 10; 0;

...или это не возможно? просто мне хочется чтоб результатом было что-то похожее на массив представленный мною в первом посте.. или что-то на него подобное....
Back to top
View user's profile Send private message
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Tue Dec 05, 2006 6:34 pm (спустя 5 минут; написано за 1 минуту 9 секунд)
   Post subject:
Reply with quote

Code (SQL): скопировать код в буфер обмена
SELECT s.SkillID, s.SkillName, s.MaxLev, p.NeedLev, p.ParentID FROM `Skills` s LEFT JOIN `Parents` p USING(SkillID)
?
Back to top
View user's profile Send private message
Fally
Заглянувший



Joined: 02 Dec 2006
Posts: 10
Карма: -1
   поощрить/наказать


PostPosted: Tue Dec 05, 2006 8:40 pm (спустя 2 часа 5 минут; написано за 2 минуты 28 секунд)
   Post subject:
Reply with quote

Выражаю глубокую признательность всем тем, кто помогал мне в этом топике, отдельная благодарность WingedFox, за может быть самый короткий, но точный ответ.
Но у меня появился и ещё один вопрос... можно ли средствами MySQL5 и РНР5 привести выбранные результаты к виду массива, приведенного мной в первом сообщении??
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Tue Dec 05, 2006 10:38 pm (спустя 1 час 58 минут; написано за 35 секунд)
   Post subject:
Reply with quote

Fally
С помощью PHP Вы с пришедшими данными может сделать всё, что возможно
Back to top
View user's profile Send private message
Fally
Заглянувший



Joined: 02 Dec 2006
Posts: 10
Карма: -1
   поощрить/наказать


PostPosted: Wed Dec 06, 2006 11:36 pm (спустя 1 день 57 минут; написано за 4 минуты 36 секунд)
   Post subject:
Reply with quote

Да я понимаю... но дело в том, что мне при разработке нельзя забывать и о быстродействии а вся проблема состоит к правильному подходу в создании правильного алгоритма для формирования массива..., т.е. получается что я создаю в цикле промежуточные массив куда записываю поочерёдно полученные из запроса данные и тут же вытаскивать из базы необходимую информацию о родителях, во вложенном цикле перебирать её и соединять в необходимый массив с данными полученными из предыдущего запроса.
Но как мне кажется, эта процедура будет очень ресурсоёмка, и будет "съедать" много системных ресурсов уже при 100 пользователях онлайн. НО эта процедура будет использоваться не так чато.. т.е. только при прокачивании умений... насколько оправдан такой подход к решению задачи? и есть ли более быстрые варианты?
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Thu Dec 07, 2006 10:53 am (спустя 11 часов 17 минут; написано за 3 минуты 17 секунд)
   Post subject:
Reply with quote

Fally
Сколько у Вас различных скиллов на класс будет будет? 20-30 ? Это смехотворный объем. В худшем случае можно будет парсить один раз - при редактриовании скиллов, а потом уже готовый массив хранить где-нибудь в сериализованном виде
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Page 1 of 1    Email to a Friend.
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML